using System;
using System.Collections.Generic;

namespace Mvc.XForms.Utilities {
	public static class NullableHelper {
		private delegate T ParseDelegate<T>(string s);

		private static Nullable<T> ParseNullable<T>(string s, ParseDelegate<T> parse) where T : struct {
			if (string.IsNullOrEmpty(s))
				return null;
			else
				return parse(s);
		}

		public static int? ParseInt(string s) {
			return ParseNullable<int>(s, int.Parse);
		}

		public static int? ParseNullableInt(this string text) {
			return ParseInt(text);
		}

		public static int ParseIntDefault(this string text, int defaultValue) {
			return ParseNullableInt(text) ?? defaultValue;
		}

		public static DateTime? ParseDateTime(string dateTime) {
			return ParseNullable<DateTime>(dateTime, DateTime.Parse);
		}

		public static DateTime? ParseNullableDateTime(this string text) {
			return ParseDateTime(text);
		}

		public static DateTime ParseDateTimeDefault(this string text, DateTime defaultValue) {
			return ParseNullableDateTime(text) ?? defaultValue;
		}

		public static bool IsNullable(Type T) {
			return (T.IsGenericType && T.GetGenericTypeDefinition() == typeof(Nullable<>));
		}

		public delegate bool TryParseDelegate<T>(string s, out T result);

		public static bool TryParseNullable<T>(string value, out Nullable<T> result, TryParseDelegate<T> tryParse) where T : struct {
			if (string.IsNullOrEmpty(value)) {
				result = null;
				return false;
			} else {
				T temp;
				bool success = tryParse(value, out temp);
				result = temp;
				return success;
			}
		}

		public static bool TryParseNullableDateTime(string s, out DateTime? result) {
			return TryParseNullable<DateTime>(s, out result, DateTime.TryParse);
		}
	}
}